package com.cicadalane.androlate;

/*
 * Copyright (C) 2011 cicada.software@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Androlate {
	public static final String OPTION_KEY_BACKUP_FILES = "BACKUP_FILES";
	public static final String OPTION_KEY_OVERWRITE_EXISTING = "overwrite_existing";
	public static final String OPTION_KEY_REMEMBER_SETTINGS = "remember_settings";
	public static final String OPTION_KEY_TRANSLATE_EVERYTHING = "translate_everything";
	public static final String OPTION_KEY_SUBMIT_UNCHANGED = "submit_unchanged";
	
	private static void loadStringDataList(ArrayList<StringData> sl,
			String elementName, Element parent) {
		List<Element> listElements = XmlUtils.getChildrenByTagName(parent,
				elementName);
		for (Element listElement : listElements) {
			List<Element> stringElements = XmlUtils.getChildrenByTagName(
					listElement, "string");
			for (Element stringElement : stringElements) {
				Element nameElement = XmlUtils.getFirstChildByTagName(
						stringElement, "name");
				Element valueElement = XmlUtils.getFirstChildByTagName(
						stringElement, "value");
				Element indexElement = XmlUtils.getFirstChildByTagName(
						stringElement, "index");

				StringData sd = new StringData();
				if (nameElement != null)
					sd.setName(nameElement.getTextContent());

				if (valueElement != null)
					sd.setValue(valueElement.getTextContent());
				if (indexElement != null)
					sd
							.setIndex(Integer.parseInt(indexElement
									.getTextContent()));
				sl.add(sd);
			}
		}
	}
	private static void writeStringDataList(ArrayList<StringData> sl,
			String elementName, Element parent) throws DOMException, Exception {
		Document doc = parent.getOwnerDocument();
		Element listElement = doc.createElement(elementName);
		parent.appendChild(listElement);
		for (StringData s : sl) {
			Element stringElement = doc.createElement("string");
			Element nameElement = doc.createElement("name");
			Element valueElement = doc.createElement("value");

			nameElement.setTextContent(s.getName());
			valueElement.setTextContent(s.getValue());

			stringElement.appendChild(nameElement);
			stringElement.appendChild(valueElement);
			if (s.hasIndex()) {
				Element indexElement = doc.createElement("index");
				indexElement.setTextContent(Integer.toString(s.getIndex()));
				stringElement.appendChild(indexElement);
			}
			listElement.appendChild(stringElement);
		}
	}
	private ArrayList<AndrolateOperation> mOperations;
	
	private Hashtable<String, String> mOptions;

	private ArrayList<AndrolateLanguage> mTargetLanguages;

	public Androlate() {
		mOperations = new ArrayList<AndrolateOperation>();
		mTargetLanguages = new ArrayList<AndrolateLanguage>();
		mOptions = new Hashtable<String, String>();
	}

	public boolean getIsOverwriteExistingSet() {
		String overwriteOptionString = getOption(Androlate.OPTION_KEY_OVERWRITE_EXISTING);
		return Boolean.parseBoolean(overwriteOptionString);
	}

	public ArrayList<AndrolateOperation> getOperations() {
		return mOperations;
	}


	public String getOption(String key) {
		return mOptions.get(key);
	}

	public ArrayList<AndrolateLanguage> getTargetLanguages() {
		return mTargetLanguages;
	}
	
	public void loadFromFile(File f) throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		Document doc = null;
		DocumentBuilder db = dbf.newDocumentBuilder();
		doc = db.parse(f);
		if (doc == null)
			throw new Exception("Unable to parse file " + f.getAbsolutePath());

		Element documentElement = doc.getDocumentElement();
		if (!documentElement.getNodeName().equals("Androlate"))
			throw new Exception(f.getAbsolutePath()
					+ " is not an Androlate document");

		List<Element> operationElements = XmlUtils.getChildrenByTagName(
				documentElement, "operation");
		for (Element operationElement : operationElements) {
			AndrolateOperation o = new AndrolateOperation();

			List<Element> filenameElements = XmlUtils.getChildrenByTagName(
					operationElement, "filename");
			if (filenameElements != null && filenameElements.size() > 0)
				o.setFilename(filenameElements.get(0).getTextContent());

			Androlate.loadStringDataList(o.getTranslateList(), "translate",
					operationElement);
			Androlate.loadStringDataList(o.getIgnoreList(), "ignore",
					operationElement);
			Androlate.loadStringDataList(o.getAllStringsList(), "allstrings",
					operationElement);
			this.getOperations().add(o);
		}

		List<Element> targetLanguageElements = XmlUtils.getChildrenByTagName(
				documentElement, "target_language");
		for (Element targetLanguageElement : targetLanguageElements) {
			Element displayElement = XmlUtils.getFirstChildByTagName(
					targetLanguageElement, "display");
			Element iso639_1Element = XmlUtils.getFirstChildByTagName(
					targetLanguageElement, "iso639_1");
			Element directoryElement = XmlUtils.getFirstChildByTagName(
					targetLanguageElement, "directory");

			if (displayElement == null || iso639_1Element == null)
				continue;
			AndrolateLanguage l = null;
			if (directoryElement == null)
				l = new AndrolateLanguage(displayElement.getTextContent(),
						iso639_1Element.getTextContent());
			else
				l = new AndrolateLanguage(displayElement.getTextContent(),
						iso639_1Element.getTextContent(), directoryElement
								.getTextContent());

			this.getTargetLanguages().add(l);
		}
	}

	public void setOption(String key, boolean value) {
		setOption(key, Boolean.toString(value));
	}

	
	public void setOption(String key, String value) {
		if (mOptions.contains(key))
			mOptions.remove(key);
		mOptions.put(key, value);
	}

	public void writeToFile(String filename) throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		Document doc = null;
		DocumentBuilder db = dbf.newDocumentBuilder();
		doc = db.newDocument();
		if (doc == null)
			throw new Exception("Unable to create new document object");

		Element documentElement = doc.createElement("Androlate");
		doc.appendChild(documentElement);

		for (AndrolateOperation o : getOperations()) {
			Element operationElement = doc.createElement("operation");

			Element filenameElement = doc.createElement("filename");
			filenameElement.setTextContent(o.getFilename());
			operationElement.appendChild(filenameElement);

			Androlate.writeStringDataList(o.getTranslateList(), "translate",
					operationElement);
			Androlate.writeStringDataList(o.getIgnoreList(), "ignore",
					operationElement);
			Androlate.writeStringDataList(o.getAllStringsList(), "allstrings",
					operationElement);

			documentElement.appendChild(operationElement);
		}

		for (AndrolateLanguage l : getTargetLanguages()) {
			Element targetLanguageElement = doc
					.createElement("target_language");
			Element displayElement = doc.createElement("display");
			Element iso639_1Element = doc.createElement("iso639_1");
			Element directoryElement = doc.createElement("directory");

			displayElement.setTextContent(l.getDisplay());
			iso639_1Element.setTextContent(l.getISO639_1());
			directoryElement.setTextContent(l.getDirectory());

			targetLanguageElement.appendChild(displayElement);
			targetLanguageElement.appendChild(iso639_1Element);
			targetLanguageElement.appendChild(directoryElement);

			documentElement.appendChild(targetLanguageElement);
		}

		XmlUtils.writeXmlFile(doc, filename);
	}
}
